home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 039a / jpsrc2.zip / JCPIPE.C < prev    next >
C/C++ Source or Header  |  1991-12-01  |  27KB  |  718 lines

  1. /*
  2.  * jcpipe.c
  3.  *
  4.  * Copyright (C) 1991, Thomas G. Lane.
  5.  * This file is part of the Independent JPEG Group's software.
  6.  * For conditions of distribution and use, see the accompanying README file.
  7.  *
  8.  * This file contains compression pipeline controllers.
  9.  * These routines are invoked via the c_pipeline_controller method.
  10.  *
  11.  * There are four basic pipeline controllers, one for each combination of:
  12.  *    single-scan JPEG file (single component or fully interleaved)
  13.  *  vs. multiple-scan JPEG file (noninterleaved or partially interleaved).
  14.  *
  15.  *    optimization of entropy encoding parameters
  16.  *  vs. usage of default encoding parameters.
  17.  *
  18.  * Note that these conditions determine the needs for "big" arrays:
  19.  * multiple scans imply a big array for splitting the color components;
  20.  * entropy encoding optimization needs a big array for the MCU data.
  21.  *
  22.  * All but the simplest controller (single-scan, no optimization) can be
  23.  * compiled out through configuration options, if you need to make a minimal
  24.  * implementation.
  25.  */
  26.  
  27. #include "jinclude.h"
  28.  
  29.  
  30. /*
  31.  * About the data structures:
  32.  *
  33.  * The processing chunk size for subsampling is referred to in this file as
  34.  * a "row group": a row group is defined as Vk (v_samp_factor) sample rows of
  35.  * any component after subsampling, or Vmax (max_v_samp_factor) unsubsampled
  36.  * rows.  In an interleaved scan each MCU row contains exactly DCTSIZE row
  37.  * groups of each component in the scan.  In a noninterleaved scan an MCU row
  38.  * is one row of blocks, which might not be an integral number of row groups;
  39.  * for convenience we use a buffer of the same size as in interleaved scans,
  40.  * and process Vk MCU rows in each burst of subsampling.
  41.  * To provide context for the subsampling step, we have to retain the last
  42.  * two row groups of the previous MCU row while reading in the next MCU row
  43.  * (or set of Vk MCU rows).  To do this without copying data about, we create
  44.  * a rather strange data structure.  Exactly DCTSIZE+2 row groups of samples
  45.  * are allocated, but we create two different sets of pointers to this array.
  46.  * The second set swaps the last two pairs of row groups.  By working
  47.  * alternately with the two sets of pointers, we can access the data in the
  48.  * desired order.
  49.  */
  50.  
  51.  
  52.  
  53. /*
  54.  * Utility routines: common code for pipeline controllers
  55.  */
  56.  
  57. LOCAL void
  58. interleaved_scan_setup (compress_info_ptr cinfo)
  59. /* Compute all derived info for an interleaved (multi-component) scan */
  60. /* On entry, cinfo->comps_in_scan and cinfo->cur_comp_info[] are set up */
  61. {
  62.   short ci, mcublks;
  63.   jpeg_component_info *compptr;
  64.  
  65.   if (cinfo->comps_in_scan > MAX_COMPS_IN_SCAN)
  66.     ERREXIT(cinfo->emethods, "Too many components for interleaved scan");
  67.  
  68.   cinfo->MCUs_per_row = (cinfo->image_width
  69.              + cinfo->max_h_samp_factor*DCTSIZE - 1)
  70.             / (cinfo->max_h_samp_factor*DCTSIZE);
  71.  
  72.   cinfo->MCU_rows_in_scan = (cinfo->image_height
  73.                  + cinfo->max_v_samp_factor*DCTSIZE - 1)
  74.                 / (cinfo->max_v_samp_factor*DCTSIZE);
  75.   
  76.   cinfo->blocks_in_MCU = 0;
  77.  
  78.   for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
  79.     compptr = cinfo->cur_comp_info[ci];
  80.     /* for interleaved scan, sampling factors give # of blocks per component */
  81.     compptr->MCU_width = compptr->h_samp_factor;
  82.     compptr->MCU_height = compptr->v_samp_factor;
  83.     compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
  84.     /* compute physical dimensions of component */
  85.     compptr->subsampled_width = jround_up(compptr->true_comp_width,
  86.                       (long) (compptr->MCU_width*DCTSIZE));
  87.     compptr->subsampled_height = jround_up(compptr->true_comp_height,
  88.                        (long) (compptr->MCU_height*DCTSIZE));
  89.     /* Sanity check */
  90.     if (compptr->subsampled_width !=
  91.     (cinfo->MCUs_per_row * (compptr->MCU_width*DCTSIZE)))
  92.       ERREXIT(cinfo->emethods, "I'm confused about the image width");
  93.     /* Prepare array describing MCU composition */
  94.     mcublks = compptr->MCU_blocks;
  95.     if (cinfo->blocks_in_MCU + mcublks > MAX_BLOCKS_IN_MCU)
  96.       ERREXIT(cinfo->emethods, "Sampling factors too large for interleaved scan");
  97.     while (mcublks-- > 0) {
  98.       cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci;
  99.     }
  100.   }
  101.  
  102.   (*cinfo->methods->c_per_scan_method_selection) (cinfo);
  103. }
  104.  
  105.  
  106. LOCAL void
  107. noninterleaved_scan_setup (compress_info_ptr cinfo)
  108. /* Compute all derived info for a noninterleaved (single-component) scan */
  109. /* On entry, cinfo->comps_in_scan = 1 and cinfo->cur_comp_info[0] is set up */
  110. {
  111.   jpeg_component_info *compptr = cinfo->cur_comp_info[0];
  112.  
  113.   /* for noninterleaved scan, always one block per MCU */
  114.   compptr->MCU_width = 1;
  115.   compptr->MCU_height = 1;
  116.   compptr->MCU_blocks = 1;
  117.   /* compute physical dimensions of component */
  118.   compptr->subsampled_width = jround_up(compptr->true_comp_width,
  119.                     (long) DCTSIZE);
  120.   compptr->subsampled_height = jround_up(compptr->true_comp_height,
  121.                      (long) DCTSIZE);
  122.  
  123.   cinfo->MCUs_per_row = compptr->subsampled_width / DCTSIZE;
  124.   cinfo->MCU_rows_in_scan = compptr->subsampled_height / DCTSIZE;
  125.  
  126.   /* Prepare array describing MCU composition */
  127.   cinfo->blocks_in_MCU = 1;
  128.   cinfo->MCU_membership[0] = 0;
  129.  
  130.   (*cinfo->methods->c_per_scan_method_selection) (cinfo);
  131. }
  132.  
  133.  
  134.  
  135. LOCAL void
  136. alloc_sampling_buffer (compress_info_ptr cinfo, JSAMPIMAGE fullsize_data[2],
  137.                long fullsize_width)
  138. /* Create a pre-subsampling data buffer having the desired structure */
  139. /* (see comments at head of file) */
  140. {
  141.   short ci, vs, i;
  142.  
  143.   vs = cinfo->max_v_samp_factor; /* row group height */
  144.  
  145.   /* Get top-level space for array pointers */
  146.   fullsize_data[0] = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
  147.                 (cinfo->num_components * SIZEOF(JSAMPARRAY));
  148.   fullsize_data[1] = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
  149.                 (cinfo->num_components * SIZEOF(JSAMPARRAY));
  150.  
  151.   for (ci = 0; ci < cinfo->num_components; ci++) {
  152.     /* Allocate the real storage */
  153.     fullsize_data[0][ci] = (*cinfo->emethods->alloc_small_sarray)
  154.                 (fullsize_width,
  155.                 (long) (vs * (DCTSIZE+2)));
  156.     /* Create space for the scrambled-order pointers */
  157.     fullsize_data[1][ci] = (JSAMPARRAY) (*cinfo->emethods->alloc_small)
  158.                 (vs * (DCTSIZE+2) * SIZEOF(JSAMPROW));
  159.     /* Duplicate the first DCTSIZE-2 row groups */
  160.     for (i = 0; i < vs * (DCTSIZE-2); i++) {
  161.       fullsize_data[1][ci][i] = fullsize_data[0][ci][i];
  162.     }
  163.     /* Copy the last four row groups in swapped order */
  164.     for (i = 0; i < vs * 2; i++) {
  165.       fullsize_data[1][ci][vs*DCTSIZE + i] = fullsize_data[0][ci][vs*(DCTSIZE-2) + i];
  166.       fullsize_data[1][ci][vs*(DCTSIZE-2) + i] = fullsize_data[0][ci][vs*DCTSIZE + i];
  167.     }
  168.   }
  169. }
  170.  
  171.  
  172. LOCAL void
  173. free_sampling_buffer (compress_info_ptr cinfo, JSAMPIMAGE fullsize_data[2])
  174. /* Release a sampling buffer created by alloc_sampling_buffer */
  175. {
  176.   short ci, vs;
  177.  
  178.   vs = cinfo->max_v_samp_factor; /* row group height */
  179.  
  180.   for (ci = 0; ci < cinfo->num_components; ci++) {
  181.     /* Free the real storage */
  182.     (*cinfo->emethods->free_small_sarray)
  183.         (fullsize_data[0][ci], (long) (vs * (DCTSIZE+2)));
  184.     /* Free the scrambled-order pointers */
  185.     (*cinfo->emethods->free_small) ((void *) fullsize_data[1][ci]);
  186.   }
  187.  
  188.   /* Free the top-level space */
  189.   (*cinfo->emethods->free_small) ((void *) fullsize_data[0]);
  190.   (*cinfo->emethods->free_small) ((void *) fullsize_data[1]);
  191. }
  192.  
  193.  
  194. LOCAL void
  195. subsample (compress_info_ptr cinfo,
  196.        JSAMPIMAGE fullsize_data, JSAMPIMAGE subsampled_data,
  197.        long fullsize_width,
  198.        short above, short current, short below, short out)
  199. /* Do subsampling of a single row group (of each component). */
  200. /* above, current, below are indexes of row groups in fullsize_data;      */
  201. /* out is the index of the target row group in subsampled_data.           */
  202. /* Special case: above, below can be -1 to indicate top, bottom of image. */
  203. {
  204.   jpeg_component_info *compptr;
  205.   JSAMPARRAY above_ptr, below_ptr;
  206.   JSAMPROW dummy[MAX_SAMP_FACTOR]; /* for subsample expansion at top/bottom */
  207.   short ci, vs, i;
  208.  
  209.   vs = cinfo->max_v_samp_factor; /* row group height */
  210.  
  211.   for (ci = 0; ci < cinfo->num_components; ci++) {
  212.     compptr = & cinfo->comp_info[ci];
  213.  
  214.     if (above >= 0)
  215.       above_ptr = fullsize_data[ci] + above * vs;
  216.     else {
  217.       /* Top of image: make a dummy above-context with copies of 1st row */
  218.       /* We assume current=0 in this case */
  219.       for (i = 0; i < vs; i++)
  220.     dummy[i] = fullsize_data[ci][0];
  221.       above_ptr = (JSAMPARRAY) dummy; /* possible near->far pointer conv */
  222.     }
  223.  
  224.     if (below >= 0)
  225.       below_ptr = fullsize_data[ci] + below * vs;
  226.     else {
  227.       /* Bot of image: make a dummy below-context with copies of last row */
  228.       for (i = 0; i < vs; i++)
  229.     dummy[i] = fullsize_data[ci][(current+1)*vs-1];
  230.       below_ptr = (JSAMPARRAY) dummy; /* possible near->far pointer conv */
  231.     }
  232.  
  233.     (*cinfo->methods->subsample[ci])
  234.         (cinfo, (int) ci,
  235.          fullsize_width, (int) vs,
  236.          compptr->subsampled_width, (int) compptr->v_samp_factor,
  237.          above_ptr,
  238.          fullsize_data[ci] + current * vs,
  239.          below_ptr,
  240.          subsampled_data[ci] + out * compptr->v_samp_factor);
  241.   }
  242. }
  243.  
  244.  
  245. /* These vars are initialized by the pipeline controller for use by
  246.  * MCU_output_catcher.
  247.  * To avoid a lot of row-pointer overhead, we cram as many MCUs into each
  248.  * row of whole_scan_MCUs as we can get without exceeding 64KB per row.
  249.  */
  250.  
  251. #define MAX_WHOLE_ROW_BLOCKS    ((int) (65500 / SIZEOF(JBLOCK))) /* max blocks/row */
  252.  
  253. static big_barray_ptr whole_scan_MCUs; /* Big array for saving the MCUs */
  254. static int MCUs_in_big_row;    /* # of MCUs in each row of whole_scan_MCUs */
  255. static long next_whole_row;    /* next row to access in whole_scan_MCUs */
  256. static int next_MCU_index;    /* next MCU in current row */
  257.  
  258.  
  259. METHODDEF void
  260. MCU_output_catcher (compress_info_ptr cinfo, JBLOCK *MCU_data)
  261. /* Output method for siphoning off extract_MCUs output into a big array */
  262. {
  263.   static JBLOCKARRAY rowptr;
  264.  
  265.   if (next_MCU_index >= MCUs_in_big_row) {
  266.     rowptr = (*cinfo->emethods->access_big_barray) (whole_scan_MCUs,
  267.                             next_whole_row, TRUE);
  268.     next_whole_row++;
  269.     next_MCU_index = 0;
  270.   }
  271.  
  272.   /*
  273.    * note that on 80x86, the cast applied to MCU_data implies
  274.    * near to far pointer conversion.
  275.    */
  276.   jcopy_block_row((JBLOCKROW) MCU_data,
  277.           rowptr[0] + next_MCU_index * cinfo->blocks_in_MCU,
  278.           (long) cinfo->blocks_in_MCU);
  279.   next_MCU_index++;
  280. }
  281.  
  282.  
  283. METHODDEF void
  284. dump_scan_MCUs (compress_info_ptr cinfo, MCU_output_method_ptr output_method)
  285. /* Dump the MCUs saved in whole_scan_MCUs to the output method. */
  286. /* The method may be either the entropy encoder or some routine supplied */
  287. /* by the entropy optimizer. */
  288. {
  289.   /* On an 80x86 machine, the entropy encoder expects the passed data block
  290.    * to be in NEAR memory (for performance reasons), so we have to copy it
  291.    * back from the big array to a local array.  On less brain-damaged CPUs
  292.    * we needn't do that.
  293.    */
  294. #ifdef NEED_FAR_POINTERS
  295.   JBLOCK MCU_data[MAX_BLOCKS_IN_MCU];
  296. #endif
  297.   long mcurow, mcuindex, next_row;
  298.   int next_index;
  299.   JBLOCKARRAY rowptr = NULL;    /* init only to suppress compiler complaint */
  300.  
  301.   next_row = 0;
  302.   next_index = MCUs_in_big_row;
  303.  
  304.   for (mcurow = 0; mcurow < cinfo->MCU_rows_in_scan; mcurow++) {
  305.     for (mcuindex = 0; mcuindex < cinfo->MCUs_per_row; mcuindex++) {
  306.       if (next_index >= MCUs_in_big_row) {
  307.     rowptr = (*cinfo->emethods->access_big_barray) (whole_scan_MCUs,
  308.                             next_row, FALSE);
  309.     next_row++;
  310.     next_index = 0;
  311.       }
  312. #ifdef NEED_FAR_POINTERS
  313.       jcopy_block_row(rowptr[0] + next_index * cinfo->blocks_in_MCU,
  314.               (JBLOCKROW) MCU_data, /* note cast */
  315.               (long) cinfo->blocks_in_MCU);
  316.       (*output_method) (cinfo, MCU_data);
  317. #else
  318.       (*output_method) (cinfo, rowptr[0] + next_index * cinfo->blocks_in_MCU);
  319. #endif
  320.       next_index++;
  321.     }
  322.   }
  323. }
  324.  
  325.  
  326.  
  327. /*
  328.  * Compression pipeline controller used for single-scan files
  329.  * with no optimization of entropy parameters.
  330.  */
  331.  
  332. METHODDEF void
  333. single_ccontroller (compress_info_ptr cinfo)
  334. {
  335.   int rows_in_mem;        /* # of sample rows in full-size buffers */
  336.   long fullsize_width;        /* # of samples per row in full-size buffers */
  337.   long cur_pixel_row;        /* counts # of pixel rows processed */
  338.   long mcu_rows_output;        /* # of MCU rows actually emitted */
  339.   int mcu_rows_per_loop;    /* # of MCU rows processed per outer loop */
  340.   /* Work buffer for pre-subsampling data (see comments at head of file) */
  341.   JSAMPIMAGE fullsize_data[2];
  342.   /* Work buffer for subsampled data */
  343.   JSAMPIMAGE subsampled_data;
  344.   int rows_this_time;
  345.   short ci, whichss, i;
  346.  
  347.   /* Prepare for single scan containing all components */
  348.   if (cinfo->num_components > MAX_COMPS_IN_SCAN)
  349.     ERREXIT(cinfo->emethods, "Too many components for interleaved scan");
  350.   cinfo->comps_in_scan = cinfo->num_components;
  351.   for (ci = 0; ci < cinfo->num_components; ci++) {
  352.     cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci];
  353.   }
  354.   if (cinfo->comps_in_scan == 1) {
  355.     noninterleaved_scan_setup(cinfo);
  356.     /* Vk block rows constitute the same number of MCU rows */
  357.     mcu_rows_per_loop = cinfo->cur_comp_info[0]->v_samp_factor;
  358.   } else {
  359.     interleaved_scan_setup(cinfo);
  360.     /* in an interleaved scan, one MCU row contains Vk block rows */
  361.     mcu_rows_per_loop = 1;
  362.   }
  363.  
  364.   /* Compute dimensions of full-size pixel buffers */
  365.   /* Note these are the same whether interleaved or not. */
  366.   rows_in_mem = cinfo->max_v_samp_factor * DCTSIZE;
  367.   fullsize_width = jround_up(cinfo->image_width,
  368.                  (long) (cinfo->max_h_samp_factor * DCTSIZE));
  369.  
  370.   /* Allocate working memory: */
  371.   /* fullsize_data is sample data before subsampling */
  372.   alloc_sampling_buffer(cinfo, fullsize_data, fullsize_width);
  373.   /* subsampled_data is sample data after subsampling */
  374.   subsampled_data = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
  375.                 (cinfo->num_components * SIZEOF(JSAMPARRAY));
  376.   for (ci = 0; ci < cinfo->num_components; ci++) {
  377.     subsampled_data[ci] = (*cinfo->emethods->alloc_small_sarray)
  378.             (cinfo->comp_info[ci].subsampled_width,
  379.              (long) (cinfo->comp_info[ci].v_samp_factor * DCTSIZE));
  380.   }
  381.  
  382.   /* Tell the memory manager to instantiate big arrays.
  383.    * We don't need any big arrays in this controller,
  384.    * but some other module (like the input file reader) may need one.
  385.    */
  386.   (*cinfo->emethods->alloc_big_arrays)
  387.     ((long) 0,                /* no more small sarrays */
  388.      (long) 0,                /* no more small barrays */
  389.      (long) 0);                /* no more "medium" objects */
  390.  
  391.   /* Initialize output file & do per-scan object init */
  392.  
  393.   (*cinfo->methods->write_scan_header) (cinfo);
  394.   cinfo->methods->entropy_output = cinfo->methods->write_jpeg_data;
  395.   (*cinfo->methods->entropy_encoder_init) (cinfo);
  396.   (*cinfo->methods->subsample_init) (cinfo);
  397.   (*cinfo->methods->extract_init) (cinfo);
  398.  
  399.   /* Loop over input image: rows_in_mem pixel rows are processed per loop */
  400.  
  401.   mcu_rows_output = 0;
  402.   whichss = 1;            /* arrange to start with fullsize_data[0] */
  403.  
  404.   for (cur_pixel_row = 0; cur_pixel_row < cinfo->image_height;
  405.        cur_pixel_row += rows_in_mem) {
  406.     whichss ^= 1;        /* switch to other fullsize_data buffer */
  407.     
  408.     /* Obtain rows_this_time pixel rows and expand to rows_in_mem rows. */
  409.     /* Then we have exactly DCTSIZE row groups for subsampling. */   
  410.     rows_this_time = (int) MIN((long) rows_in_mem,
  411.                    cinfo->image_height - cur_pixel_row);
  412.  
  413.     (*cinfo->methods->get_sample_rows) (cinfo, rows_this_time,
  414.                     fullsize_data[whichss]);
  415.     (*cinfo->methods->edge_expand) (cinfo,
  416.                     cinfo->image_width, rows_this_time,
  417.                     fullsize_width, rows_in_mem,
  418.                     fullsize_data[whichss]);
  419.     
  420.     /* Subsample the data (all components) */
  421.     /* First time through is a special case */
  422.     
  423.     if (cur_pixel_row) {
  424.       /* Subsample last row group of previous set */
  425.       subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
  426.         (short) DCTSIZE, (short) (DCTSIZE+1), (short) 0,
  427.         (short) (DCTSIZE-1));
  428.       /* and dump the previous set's subsampled data */
  429.       (*cinfo->methods->extract_MCUs) (cinfo, subsampled_data, 
  430.                        mcu_rows_per_loop,
  431.                        cinfo->methods->entropy_encode);
  432.       mcu_rows_output += mcu_rows_per_loop;
  433.       /* Subsample first row group of this set */
  434.       subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
  435.         (short) (DCTSIZE+1), (short) 0, (short) 1,
  436.         (short) 0);
  437.     } else {
  438.       /* Subsample first row group with dummy above-context */
  439.       subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
  440.         (short) (-1), (short) 0, (short) 1,
  441.         (short) 0);
  442.     }
  443.     /* Subsample second through next-to-last row groups of this set */
  444.     for (i = 1; i <= DCTSIZE-2; i++) {
  445.       subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
  446.         (short) (i-1), (short) i, (short) (i+1),
  447.         (short) i);
  448.     }
  449.   } /* end of outer loop */
  450.   
  451.   /* Subsample the last row group with dummy below-context */
  452.   /* Note whichss points to last buffer side used */
  453.   subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
  454.         (short) (DCTSIZE-2), (short) (DCTSIZE-1), (short) (-1),
  455.         (short) (DCTSIZE-1));
  456.   /* Dump the remaining data (may be less than full height if uninterleaved) */
  457.   (*cinfo->methods->extract_MCUs) (cinfo, subsampled_data, 
  458.         (int) (cinfo->MCU_rows_in_scan - mcu_rows_output),
  459.         cinfo->methods->entropy_encode);
  460.  
  461.   /* Finish output file */
  462.   (*cinfo->methods->extract_term) (cinfo);
  463.   (*cinfo->methods->subsample_term) (cinfo);
  464.   (*cinfo->methods->entropy_encoder_term) (cinfo);
  465.   (*cinfo->methods->write_scan_trailer) (cinfo);
  466.  
  467.   /* Release working memory */
  468.   free_sampling_buffer(cinfo, fullsize_data);
  469.   for (ci = 0; ci < cinfo->num_components; ci++) {
  470.     (*cinfo->emethods->free_small_sarray)
  471.         (subsampled_data[ci],
  472.          (long) (cinfo->comp_info[ci].v_samp_factor * DCTSIZE));
  473.   }
  474.   (*cinfo->emethods->free_small) ((void *) subsampled_data);
  475. }
  476.  
  477.  
  478. /*
  479.  * Compression pipeline controller used for single-scan files
  480.  * with optimization of entropy parameters.
  481.  */
  482.  
  483. #ifdef ENTROPY_OPT_SUPPORTED
  484.  
  485. METHODDEF void
  486. single_eopt_ccontroller (compress_info_ptr cinfo)
  487. {
  488.   int rows_in_mem;        /* # of sample rows in full-size buffers */
  489.   long fullsize_width;        /* # of samples per row in full-size buffers */
  490.   long cur_pixel_row;        /* counts # of pixel rows processed */
  491.   long mcu_rows_output;        /* # of MCU rows actually emitted */
  492.   int mcu_rows_per_loop;    /* # of MCU rows processed per outer loop */
  493.   /* Work buffer for pre-subsampling data (see comments at head of file) */
  494.   JSAMPIMAGE fullsize_data[2];
  495.   /* Work buffer for subsampled data */
  496.   JSAMPIMAGE subsampled_data;
  497.   int rows_this_time;
  498.   int blocks_in_big_row;
  499.   short ci, whichss, i;
  500.  
  501.   /* Prepare for single scan containing all components */
  502.   if (cinfo->num_components > MAX_COMPS_IN_SCAN)
  503.     ERREXIT(cinfo->emethods, "Too many components for interleaved scan");
  504.   cinfo->comps_in_scan = cinfo->num_components;
  505.   for (ci = 0; ci < cinfo->num_components; ci++) {
  506.     cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci];
  507.   }
  508.   if (cinfo->comps_in_scan == 1) {
  509.     noninterleaved_scan_setup(cinfo);
  510.     /* Vk block rows constitute the same number of MCU rows */
  511.     mcu_rows_per_loop = cinfo->cur_comp_info[0]->v_samp_factor;
  512.   } else {
  513.     interleaved_scan_setup(cinfo);
  514.     /* in an interleaved scan, one MCU row contains Vk block rows */
  515.     mcu_rows_per_loop = 1;
  516.   }
  517.  
  518.   /* Compute dimensions of full-size pixel buffers */
  519.   /* Note these are the same whether interleaved or not. */
  520.   rows_in_mem = cinfo->max_v_samp_factor * DCTSIZE;
  521.   fullsize_width = jround_up(cinfo->image_width,
  522.                  (long) (cinfo->max_h_samp_factor * DCTSIZE));
  523.  
  524.   /* Allocate working memory: */
  525.   /* fullsize_data is sample data before subsampling */
  526.   alloc_sampling_buffer(cinfo, fullsize_data, fullsize_width);
  527.   /* subsampled_data is sample data after subsampling */
  528.   subsampled_data = (JSAMPIMAGE) (*cinfo->emethods->alloc_small)
  529.                 (cinfo->num_components * SIZEOF(JSAMPARRAY));
  530.   for (ci = 0; ci < cinfo->num_components; ci++) {
  531.     subsampled_data[ci] = (*cinfo->emethods->alloc_small_sarray)
  532.             (cinfo->comp_info[ci].subsampled_width,
  533.              (long) (cinfo->comp_info[ci].v_samp_factor * DCTSIZE));
  534.   }
  535.  
  536.   /* Figure # of MCUs to be packed in a row of whole_scan_MCUs */
  537.   MCUs_in_big_row = MAX_WHOLE_ROW_BLOCKS / cinfo->blocks_in_MCU;
  538.   blocks_in_big_row = MCUs_in_big_row * cinfo->blocks_in_MCU;
  539.  
  540.   /* Request a big array: whole_scan_MCUs saves the MCU data for the scan */
  541.   whole_scan_MCUs = (*cinfo->emethods->request_big_barray)
  542.         ((long) blocks_in_big_row,
  543.          (long) (cinfo->MCUs_per_row * cinfo->MCU_rows_in_scan
  544.              + MCUs_in_big_row-1) / MCUs_in_big_row,
  545.          1L);        /* unit height is 1 row */
  546.  
  547.   next_whole_row = 0;        /* init output ptr for MCU_output_catcher */
  548.   next_MCU_index = MCUs_in_big_row; /* forces access on first call! */
  549.  
  550.   /* Tell the memory manager to instantiate big arrays */
  551.   (*cinfo->emethods->alloc_big_arrays)
  552.     ((long) 0,                /* no more small sarrays */
  553.      (long) 0,                /* no more small barrays */
  554.      (long) 0);                /* no more "medium" objects */
  555.  
  556.   /* Do per-scan object init */
  557.  
  558.   (*cinfo->methods->subsample_init) (cinfo);
  559.   (*cinfo->methods->extract_init) (cinfo);
  560.  
  561.   /* Loop over input image: rows_in_mem pixel rows are processed per loop */
  562.   /* MCU data goes into whole_scan_MCUs, not to the entropy encoder */
  563.  
  564.   mcu_rows_output = 0;
  565.   whichss = 1;            /* arrange to start with fullsize_data[0] */
  566.  
  567.   for (cur_pixel_row = 0; cur_pixel_row < cinfo->image_height;
  568.        cur_pixel_row += rows_in_mem) {
  569.     whichss ^= 1;        /* switch to other fullsize_data buffer */
  570.     
  571.     /* Obtain rows_this_time pixel rows and expand to rows_in_mem rows. */
  572.     /* Then we have exactly DCTSIZE row groups for subsampling. */   
  573.     rows_this_time = (int) MIN((long) rows_in_mem,
  574.                    cinfo->image_height - cur_pixel_row);
  575.  
  576.     (*cinfo->methods->get_sample_rows) (cinfo, rows_this_time,
  577.                     fullsize_data[whichss]);
  578.     (*cinfo->methods->edge_expand) (cinfo,
  579.                     cinfo->image_width, rows_this_time,
  580.                     fullsize_width, rows_in_mem,
  581.                     fullsize_data[whichss]);
  582.     
  583.     /* Subsample the data (all components) */
  584.     /* First time through is a special case */
  585.     
  586.     if (cur_pixel_row) {
  587.       /* Subsample last row group of previous set */
  588.       subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
  589.         (short) DCTSIZE, (short) (DCTSIZE+1), (short) 0,
  590.         (short) (DCTSIZE-1));
  591.       /* and dump the previous set's subsampled data */
  592.       (*cinfo->methods->extract_MCUs) (cinfo, subsampled_data, 
  593.                        mcu_rows_per_loop,
  594.                        MCU_output_catcher);
  595.       mcu_rows_output += mcu_rows_per_loop;
  596.       /* Subsample first row group of this set */
  597.       subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
  598.         (short) (DCTSIZE+1), (short) 0, (short) 1,
  599.         (short) 0);
  600.     } else {
  601.       /* Subsample first row group with dummy above-context */
  602.       subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
  603.         (short) (-1), (short) 0, (short) 1,
  604.         (short) 0);
  605.     }
  606.     /* Subsample second through next-to-last row groups of this set */
  607.     for (i = 1; i <= DCTSIZE-2; i++) {
  608.       subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
  609.         (short) (i-1), (short) i, (short) (i+1),
  610.         (short) i);
  611.     }
  612.   } /* end of outer loop */
  613.   
  614.   /* Subsample the last row group with dummy below-context */
  615.   /* Note whichss points to last buffer side used */
  616.   subsample(cinfo, fullsize_data[whichss], subsampled_data, fullsize_width,
  617.         (short) (DCTSIZE-2), (short) (DCTSIZE-1), (short) (-1),
  618.         (short) (DCTSIZE-1));
  619.   /* Dump the remaining data (may be less than full height if uninterleaved) */
  620.   (*cinfo->methods->extract_MCUs) (cinfo, subsampled_data, 
  621.         (int) (cinfo->MCU_rows_in_scan - mcu_rows_output),
  622.         MCU_output_catcher);
  623.  
  624.   /* Clean up after that stuff, then find the optimal entropy parameters */
  625.  
  626.   (*cinfo->methods->extract_term) (cinfo);
  627.   (*cinfo->methods->subsample_term) (cinfo);
  628.  
  629.   (*cinfo->methods->entropy_optimize) (cinfo, dump_scan_MCUs);
  630.  
  631.   /* Emit scan to output file */
  632.   /* Note: we can't do write_scan_header until entropy parameters are set! */
  633.  
  634.   (*cinfo->methods->write_scan_header) (cinfo);
  635.   cinfo->methods->entropy_output = cinfo->methods->write_jpeg_data;
  636.   (*cinfo->methods->entropy_encoder_init) (cinfo);
  637.   dump_scan_MCUs(cinfo, cinfo->methods->entropy_encode);
  638.   (*cinfo->methods->entropy_encoder_term) (cinfo);
  639.   (*cinfo->methods->write_scan_trailer) (cinfo);
  640.  
  641.   /* Release working memory */
  642.   free_sampling_buffer(cinfo, fullsize_data);
  643.   for (ci = 0; ci < cinfo->num_components; ci++) {
  644.     (*cinfo->emethods->free_small_sarray)
  645.         (subsampled_data[ci],
  646.          (long) (cinfo->comp_info[ci].v_samp_factor * DCTSIZE));
  647.   }
  648.   (*cinfo->emethods->free_small) ((void *) subsampled_data);
  649.   (*cinfo->emethods->free_big_barray) (whole_scan_MCUs);
  650. }
  651.  
  652. #endif /* ENTROPY_OPT_SUPPORTED */
  653.  
  654.  
  655. /*
  656.  * Compression pipeline controller used for multiple-scan files
  657.  * with no optimization of entropy parameters.
  658.  */
  659.  
  660. #ifdef MULTISCAN_FILES_SUPPORTED
  661.  
  662. METHODDEF void
  663. multi_ccontroller (compress_info_ptr cinfo)
  664. {
  665.   ERREXIT(cinfo->emethods, "Not implemented yet");
  666. }
  667.  
  668. #endif /* MULTISCAN_FILES_SUPPORTED */
  669.  
  670.  
  671. /*
  672.  * Compression pipeline controller used for multiple-scan files
  673.  * with optimization of entropy parameters.
  674.  */
  675.  
  676. #ifdef MULTISCAN_FILES_SUPPORTED
  677. #ifdef ENTROPY_OPT_SUPPORTED
  678.  
  679. METHODDEF void
  680. multi_eopt_ccontroller (compress_info_ptr cinfo)
  681. {
  682.   ERREXIT(cinfo->emethods, "Not implemented yet");
  683. }
  684.  
  685. #endif /* ENTROPY_OPT_SUPPORTED */
  686. #endif /* MULTISCAN_FILES_SUPPORTED */
  687.  
  688.  
  689. /*
  690.  * The method selection routine for compression pipeline controllers.
  691.  */
  692.  
  693. GLOBAL void
  694. jselcpipeline (compress_info_ptr cinfo)
  695. {
  696.   if (cinfo->interleave || cinfo->num_components == 1) {
  697.     /* single scan needed */
  698. #ifdef ENTROPY_OPT_SUPPORTED
  699.     if (cinfo->optimize_coding)
  700.       cinfo->methods->c_pipeline_controller = single_eopt_ccontroller;
  701.     else
  702. #endif
  703.       cinfo->methods->c_pipeline_controller = single_ccontroller;
  704.   } else {
  705.     /* multiple scans needed */
  706. #ifdef MULTISCAN_FILES_SUPPORTED
  707. #ifdef ENTROPY_OPT_SUPPORTED
  708.     if (cinfo->optimize_coding)
  709.       cinfo->methods->c_pipeline_controller = multi_eopt_ccontroller;
  710.     else
  711. #endif
  712.       cinfo->methods->c_pipeline_controller = multi_ccontroller;
  713. #else
  714.     ERREXIT(cinfo->emethods, "Multiple-scan support was not compiled");
  715. #endif
  716.   }
  717. }
  718.